package com.develop.tools;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

public class ObjectInvoice {

    private static final Logger LOGGER = LoggerFactory.getLogger(ObjectInvoice.class);

    @Resource
    private InvoiceMapper invoiceMapper;

    @Repository
    public interface InvoiceMapper {

        List<InvoiceObject> acquireName();
    }

    @Data
    public class InvoiceObject implements Serializable {

        /**
         * 类的全额限定名
         */
        private String className;

        /**
         * 方法名称【className类的方法名】
         */
        private String methodName;

        /**
         * 方法名形参的类的全额限定名【methodName】
         */
        private String[] paramTypes;

        /**
         * 方法的参数值
         */
        private Object[] params;
    }

    public void invoke() {
        List<InvoiceObject> invoiceObjectList = invoiceMapper.acquireName();
        if (!CollectionUtils.isEmpty(invoiceObjectList)) {
            for (InvoiceObject invoice : invoiceObjectList) {
                try {// 加载类
                    Class<?> aClass = Class.forName(invoice.getClassName());
                    // 假设有默认构造方法
                    Object o = aClass.getDeclaredConstructor().newInstance();
                    // 准备参数类型数组
                    Class<?>[] classes = new Class[invoice.getParamTypes().length];
                    for (int i = 0; i < invoice.getParamTypes().length; i++) {
                        classes[i] = Class.forName(invoice.getParamTypes()[i]);
                    }
                    // 获取方法
                    Method method = aClass.getDeclaredMethod(invoice.getMethodName(), classes);
                    // 如果方法是私有的，设置为可访问
                    if (!method.isAccessible()) {
                        method.setAccessible(true);
                    }
                    // 调用方法
                    method.invoke(o, invoice.getParams());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        String className = "com.yu.domain.Nexus";
        String methodName = "acquireNexus";

        // 示例1：使用String参数
        String[] stringParamTypes = {"java.lang.String"};
        Object[] stringParams = {"hello world!"};
        new ObjectInvoice().invoke();

        // 示例2：使用Integer参数（假设acquireNexus有一个重载版本接受Integer）
        String[] integerParamTypes = {"java.lang.Integer"};
        Object[] integerParams = {123}; // 注意这里使用了自动装箱，实际上是Integer.valueOf(123)
        new ObjectInvoice().invoke();
    }
}
